﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MyAlbum.Data;
using MyAlbum.Model;
using MyAlbum.Services;
using PersonalAlbum.Caching;
using PersonalAlbum.Controllers;
using System.Web.Security;
using MyAlbum.Logging;
using Autofac;
using Autofac.Builder;
using System.Web.Mvc;
using System.Reflection;


namespace PersonalAlbum
{
    public class ObjectFactory
    {
        //private static IKernel kernel;
        private static IContainer _container;
        static ObjectFactory()
        {
            if (_container == null)
            {
                var builder = new ContainerBuilder();
                //builder.SetDefaultScope(InstanceScope.Factory);
                IConfiguration config = new MyAlbum.Services.Configuration(HttpContext.Current.Server.MapPath("~"));
                builder.Register(c => config).As<IConfiguration>().WithScope(InstanceScope.Singleton);
                //this will register all the controllers
                if (config.PersistenceMode == PersistenceModes.LinqToSql)
                {
                    RegisterLinqRepositories(builder, config);
                }
                else if (config.PersistenceMode == PersistenceModes.Xml)
                {
                    RegisterXmlRepositories(builder);
                }
                RegisterTools(builder);
                RegisterServices(builder);
                
                _container = builder.Build();
            }
            //    if (kernel == null)
            //    {
            //        kernel = new StandardKernel(new CustomModule());
            //    }
        }

        private static void RegisterServices(ContainerBuilder builder)
        {
            //  builder.Register<ConfigService>().As<IDataService<Config>>();
            builder.Register<StatisticsService>().As<IStatisticsService>().WithScope(InstanceScope.Container);
            builder.Register<BlogService>().As<IBlogService>().WithScope(InstanceScope.Factory);
            builder.Register<EntranceService>().As<IDataService<Entrance>>().WithScope(InstanceScope.Factory);
            builder.Register<TagEntryService>().As<ITagEntryService>().WithScope(InstanceScope.Factory);
            builder.Register<Log4Net>().As<ILogger>();
            builder.Register<EntryService>().As<IEntryService>().WithScope(InstanceScope.Factory);
            builder.Register<SectionService>().As<ISectionService>().WithScope(InstanceScope.Factory);
            builder.Register<AlbumService>().As<IAlbumService>().WithScope(InstanceScope.Factory);
            builder.Register<SupportService>().As<IDataService<Support>>().WithScope(InstanceScope.Factory);
            builder.Register<ReplyService>().As<IDataService<Reply>>().WithScope(InstanceScope.Factory);
        }

        private static void RegisterTools(ContainerBuilder builder)
        {
            builder.Register<WebUser>().As<IUser>().WithScope(InstanceScope.Factory);
            builder.Register<ICacheService>(WebCacheManager.Instance);
            builder.Register<Lang>().As<ILanguageService>();
            builder.Register(c => Membership.Provider).As<MembershipProvider>();
            builder.Register<FormsAuthenticationWrapper>().As<IFormsAuthentication>();
        }

        private static void RegisterXmlRepositories(ContainerBuilder builder)
        {
            builder.Register(c => new MyAlbum.Data.Xml.BlogRepsitory(ConfigManager.AppDataPhysicalPath)).As<IBlogRepository>().WithScope(InstanceScope.Factory);
            var tagEntryRepository = new MyAlbum.Data.Xml.TagEntryRepository(ConfigManager.AppDataPhysicalPath);
            builder.Register(c => tagEntryRepository).As<ITagEntryRepository>().WithScope(InstanceScope.Factory);
            var repliesRepository = new MyAlbum.Data.Xml.ReplyRepository(ConfigManager.AppDataPhysicalPath);
            builder.Register(c => repliesRepository).As<IRepository<Reply>>().WithScope(InstanceScope.Factory);

            builder.Register(c => new MyAlbum.Data.Xml.EntryRepository(ConfigManager.AppDataPhysicalPath, tagEntryRepository, repliesRepository)).As<IEntryRepository>().WithScope(InstanceScope.Factory);

            builder.Register(c => new MyAlbum.Data.Xml.SectionRepository(ConfigManager.AppDataPhysicalPath)).As<ISectionRepository>().WithScope(InstanceScope.Factory);
            builder.Register(c => new MyAlbum.Data.Xml.AlbumRepository(ConfigManager.AppDataPhysicalPath)).As<IAlbumRepository>().WithScope(InstanceScope.Factory);
            //     builder.Register(c => new MyAlbum.Data.Xml.ConfigRepository(ConfigManager.AppDataPhysicalPath)).As<IRepository<Config>>();
            builder.Register(c => new MyAlbum.Data.Xml.SupportRepository(ConfigManager.AppDataPhysicalPath)).As<IRepository<Support>>().WithScope(InstanceScope.Factory);
            builder.Register(c => new MyAlbum.Data.Xml.EntranceRepository(ConfigManager.AppDataPhysicalPath)).As<IRepository<Entrance>>().WithScope(InstanceScope.Factory);
        }

        private static void RegisterLinqRepositories(ContainerBuilder builder, IConfiguration config)
        {
            //TODO: sql implementation for the blog
            builder.Register(c => new MyAlbum.Data.Xml.BlogRepsitory(ConfigManager.AppDataPhysicalPath)).As<IBlogRepository>().WithScope(InstanceScope.Factory);
            var tagEntryRepository = new MyAlbum.Data.Linq.TagEntryRepository(config.ConnectionString);
            builder.Register(c => tagEntryRepository).As<ITagEntryRepository>().WithScope(InstanceScope.Factory);
            var repliesRepository = new MyAlbum.Data.Linq.ReplyRepository(config.ConnectionString);
            builder.Register(c => repliesRepository).As<IRepository<Reply>>().WithScope(InstanceScope.Factory);

            builder.Register(c => new MyAlbum.Data.Linq.EntryRepository(config.ConnectionString)).As<IEntryRepository>().WithScope(InstanceScope.Factory);

            builder.Register(c => new MyAlbum.Data.Linq.SectionRepository(config.ConnectionString)).As<ISectionRepository>().WithScope(InstanceScope.Factory);
            builder.Register(c => new MyAlbum.Data.Linq.AlbumRepository(config.ConnectionString)).As<IAlbumRepository>().WithScope(InstanceScope.Factory);
            //     builder.Register(c => new MyAlbum.Data.Xml.ConfigRepository(ConfigManager.AppDataPhysicalPath)).As<IRepository<Config>>();
            builder.Register(c => new MyAlbum.Data.Linq.SupportRepository(config.ConnectionString)).As<IRepository<Support>>().WithScope(InstanceScope.Factory);
            builder.Register(c => new MyAlbum.Data.Linq.EntranceRepository(config.ConnectionString)).As<IRepository<Entrance>>().WithScope(InstanceScope.Factory);

        }

        private static void RegisterConrollers(ContainerBuilder builder)
        {
            builder.Register<HomeController>();
            builder.Register<EntryController>();
            builder.Register<AlbumsController>();
            builder.Register<CategoriesController>();
            builder.Register<AccountController>();
            builder.Register<ReplyController>();
            builder.Register<RssController>();
            builder.Register<SupportController>();
        }
        public static T GetInstance<T>()
        {
            //    return kernel.Get<T>();
            //  return (T)(object)new Lang();
            return _container.Resolve<T>();
        }
#if Autofac
        public static object GetInstance(Type type)
        {
            
            return _container.Resolve(type);

        //    return kernel.Get(type);
        }
#endif
    }
#if Autofac
    public class CustomModule : StandardModule
    {
        public override void Load()
        {
            Bind<ICacheService>().To<WebCacheManager>();
            Bind<IFormsAuthentication>().To<FormsAuthenticationWrapper>();
            Bind<MembershipProvider>().ToConstant(Membership.Provider);
            Bind<ILogger>().To<NLogger>();
            Bind<ILanguageService>().To<Lang>();

            Bind<ITagEntryService>()
             .To<TagEntryService>();

            Bind<IEntryService>()
             .To<EntryService>();

            Bind<ISectionService>()
                .To<SectionService>();

            Bind<IDataService<Album>>().
               To<AlbumService>();

            Bind<IDataService<Config>>().
               To<ConfigService>();

            Bind<IDataService<Support>>().
              To<SupportService>();

            Bind<IDataService<Reply>>().
               To<ReplyService>();

            Bind<IDataService<Entrance>>().
              To<EntranceService>();


            Bind<ITagEntryRepository>().ToConstant(new MyAlbum.Data.Linq.TagEntryRepository(Utils.ConnectionString));

            Bind<IEntryRepository>().ToConstant(new MyAlbum.Data.Linq.EntryRepository(Utils.ConnectionString));

            Bind<IRepository<Section>>().ToConstant(new MyAlbum.Data.Linq.SectionRepository(Utils.ConnectionString));

            Bind<IRepository<Album>>().ToConstant(new MyAlbum.Data.Linq.AlbumRepository(Utils.ConnectionString));

            Bind<IRepository<Config>>().ToConstant(new MyAlbum.Data.Linq.ConfigRepository(Utils.ConnectionString));

            Bind<IRepository<Support>>().ToConstant(new MyAlbum.Data.Linq.SupportRepository(Utils.ConnectionString));

            Bind<IRepository<Reply>>().ToConstant(new MyAlbum.Data.Linq.ReplyRepository(Utils.ConnectionString));

            Bind<IRepository<Entrance>>().ToConstant(new MyAlbum.Data.Linq.EntranceRepository(Utils.ConnectionString));
        }

    }
#endif
}
